package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.commons.constants.Constants;
import com.tanhua.commons.constants.LogKey;
import com.tanhua.commons.constants.LogType;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.vo.CommentVO;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.CommentSubject;
import com.tanhua.model.enums.CommentType;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Xiao
 * @date 2021/10/28
 */
@Service
@Slf4j
public class CommentsService {
    @DubboReference
    private CommentApi commentApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserFreezeService userFreezeService;
    @Autowired
    private MqMessageService mqMessageService;

    /**
     * 圈子-评论列表
     *
     * @param movementId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult getCommentPage(String movementId, Integer page, Integer pagesize) {
        //调用CommentApi查询评论列表信息
        List<Comment> comments = commentApi.selectByMovementId(movementId, CommentType.COMMENT, page, pagesize);
        if (CollUtil.isEmpty(comments)) {
            return new PageResult();
        }
        return getPageResult(page, pagesize, comments);
    }

    /**
     * 将List<Comment>封装为PageResult对象
     *
     * @param page
     * @param pagesize
     * @param comments
     * @return
     */
    public PageResult getPageResult(Integer page, Integer pagesize, List<Comment> comments) {
        if (CollUtil.isEmpty(comments)) {
            return new PageResult();
        }
        //调用UserApi查询用户详情
        List<Long> userIds = CollUtil.getFieldValues(comments, "userId", Long.class);
        Map<Long, UserInfo> userInfos = userInfoApi.selectByIdsAndCondition(userIds, null);
        //封装CommentVO对象
        String keyValue = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        List<CommentVO> commentVOs = new ArrayList<>();
        for (Comment comment : comments) {
            UserInfo userInfo = userInfos.get(comment.getUserId());
            //从redis获取点赞状态
            String key = Constants.MOVEMENTS_INTERACT_KEY + comment.getId().toHexString();
            CommentVO commentVO = CommentVO.init(userInfo, comment);
            if (redisTemplate.opsForHash().hasKey(key, keyValue)) {
                commentVO.setHasLiked(1);
            }
            commentVOs.add(commentVO);
        }
        //构造PageResult对象并返回
        return new PageResult(page, pagesize, 0, commentVOs);
    }

    /**
     * 圈子-发布评论
     *
     * @param movementId
     * @param comment
     */
    public void publish(String movementId, String comment, CommentSubject commentSubject) {
        //获取用户id
        Long userId = UserHolder.getUserId();
        //检查用户冻结状态
        userFreezeService.checkUserStatus("2", userId);
        //构造comment对象
        Comment commentTarget = new Comment();
        commentTarget.setPublishId(new ObjectId(movementId));
        commentTarget.setCommentType(CommentType.COMMENT.getType());
        commentTarget.setContent(comment);
        commentTarget.setUserId(userId);
        commentTarget.setCreated(System.currentTimeMillis());
        //调用CommentApi保存评论信息
        Integer countComment = commentApi.save(commentTarget, commentSubject);
        log.info("countComment:{}", countComment);
        //发送日志
        switch (commentSubject) {
            case MOVEMENT: {
                mqMessageService.sendLogMessage(
                        userId, LogType.MOVEMENT_COMMENT, LogKey.MOVEMENT, movementId);
                break;
            }
            case VIDEO: {
                mqMessageService.sendLogMessage(
                        userId, LogType.VIDEO_COMMENT, LogKey.VIDEO, movementId);
                break;
            }
            default:
                break;
        }

    }

    /**
     * 圈子-单条评论点赞、取消点赞
     *
     * @param id
     * @param choose
     * @return
     */
    public Integer disposeComment(String id, Boolean choose, CommentSubject commentSubject) {
        //查询当前状态
        Long userId = UserHolder.getUserId();
        CommentType commentType = CommentType.LIKE;
        Boolean hasCommend = commentApi.hasComment(userId, id, commentType);
        //当前状态与操作方向一致，抛出异常
        if (hasCommend && choose) {
            throw new BusinessException(ErrorResult.likeError());
        }
        if (!hasCommend && !choose) {
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //当前状态与操作方向不一致，调用CommentApi操作数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(id));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(userId);
        //拼接redis，更新用户点赞/喜欢状态
        //  key--》拼接评论id  keyValue--》拼接用户id
        String key = Constants.MOVEMENTS_INTERACT_KEY + id;
        String keyValue = Constants.MOVEMENT_LIKE_HASHKEY + userId;
        //调用API进行点赞、取消点赞操作，并返回最新数据
        Integer count = null;
        if (choose) {
            comment.setCreated(System.currentTimeMillis());
            redisTemplate.opsForHash().put(key, keyValue, "1");
            count = commentApi.save(comment, commentSubject);
        } else {
            redisTemplate.opsForHash().delete(key, keyValue, "1");
            count = commentApi.delete(comment, commentSubject);
        }
        log.info("count:{}", count);
        return count;
    }
}
